<template>
    <div class="app-container">
        <el-row :gutter="20">
            <el-col :span="24" :xs="24">
                <h4 class="office-label">角色列表</h4>
            </el-col>
        </el-row>
        <el-row>
            <el-col :span="24" :xs="24">
                <div class="head-container">
                    <el-form ref="queryRef" :inline="true" label-width="68px">
                        <el-form-item label="角色名称" prop="name">
                            <el-input @keyup.enter="handleQuery" v-model="queryParams.name" placeholder="请输入角色名称"
                                clearable />
                        </el-form-item>
                        <el-form-item label="英文名称" prop="enname">
                            <el-input @keyup.enter="handleQuery" v-model="queryParams.enname" placeholder="请输入英文名称"
                                clearable />
                        </el-form-item>
                        <el-form-item label="状态" prop="status">
                            <el-select v-model="queryParams.status" placeholder="角色状态" clearable>
                                <el-option v-for="item in use_status" :label="item.label" :value="item.value"
                                    :key="item.value"></el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="创建时间" style="width: 308px">
                            <el-date-picker clearable v-model="dateRange" value-format="YYYY-MM-DD" type="daterange"
                                range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期">
                            </el-date-picker>
                        </el-form-item>
                        <el-form-item>
                            <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
                            <el-button icon="Refresh" @click="resetQuery">重置</el-button>
                        </el-form-item>
                    </el-form>
                    <el-row :gutter="10" class="mb8">
                        <el-col :span="1.5">
                            <el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
                        </el-col>
                        <el-col :span="1.5">
                            <el-button type="success" plain icon="Edit" :disabled="hasEdit"
                                @click="handleUpdate">修改</el-button>
                        </el-col>
                        <el-col :span="1.5">
                            <el-button type="danger" plain icon="Delete" :disabled="hasDel"
                                @click="handleDelete">删除</el-button>
                        </el-col>
                    </el-row>
                </div>
            </el-col>
            <el-col :span="24" :xs="24">
                <el-table stripe ref="roleTableRef" :data="roleList" style="width: 100%"
                    @selection-change="handleSelectionChange" v-loading="loading">
                    <el-table-column type="selection" width="55" />
                    <el-table-column property="name" label="角色名称" />
                    <el-table-column property="enname" label="英文名称" />
                    <el-table-column property="officeName" label="归属机构" />
                    <el-table-column property="data_scope" label="数据范围">
                        <template #default="scope">
                            <dict-tag :options="sys_data_scope" :value="scope.row.data_scope" />
                        </template>
                    </el-table-column>
                    <el-table-column property="role_key" label="权限字符" />
                    <el-table-column property="role_type" label="角色类型" />
                    <el-table-column label="状态" align="center" key="status">
                        <template #default="scope">
                            <el-switch :disabled="scope.row.is_sys != '0' && currentUserType != '0'"
                                v-model="scope.row.status" active-value="0" inactive-value="1"
                                @change="handleStatusChange(scope.row)"></el-switch>
                        </template>
                    </el-table-column>
                    <el-table-column label="创建时间" align="center" prop="createTime">
                        <template #default="scope">
                            <span>{{ parseTime(scope.row.createTime) }}</span>
                        </template>
                    </el-table-column>
                    <el-table-column label="操作" align="center" width="250" class-name="small-padding fixed-width">
                        <template #default="scope">
                            <el-tooltip v-if="scope.row.is_sys != '1' || currentUserType == '0'" content="修改"
                                placement="top">
                                <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
                            </el-tooltip>
                            <el-tooltip v-if="scope.row.is_sys != '1' || currentUserType == '0'" content="删除"
                                placement="top">
                                <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
                            </el-tooltip>
                            <el-tooltip v-if="currentUserType == '0'" content="权限设置" placement="top">
                                <el-button link type="primary" icon="Key" @click="handleMenuAuth(scope.row)"></el-button>
                            </el-tooltip>
                            <el-tooltip v-if="scope.row.is_sys != '1' || currentUserType == '0'" content="分配用户"
                                placement="top">
                                <el-button link type="primary" icon="Switch" @click="handleAuthUser(scope.row)"></el-button>
                            </el-tooltip>
                        </template>
                    </el-table-column>
                </el-table>
                <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
                    v-model:limit="queryParams.pageSize" @pagination="bindRoleList" />
            </el-col>
        </el-row>
    
        <!-- 添加或修改角色配置对话框 -->
        <el-dialog :title="title" v-model="open" width="600px" @close="reset" append-to-body>
            <el-form :model="form" :rules="rules" ref="roleFormRef" label-width="80px">
                <el-row>
                    <el-col :span="12">
                        <el-form-item label="角色名称" prop="name">
                            <el-input v-model="form.name" clearable placeholder="请输入角色名称" />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="英文名称" prop="enname">
                            <el-input v-model="form.enname" clearable placeholder="请输入英文名称" />
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="12">
                        <el-form-item label="角色类型" prop="role_type">
                            <el-select v-model="form.role_type" placeholder="角色类型">
                                <el-option v-for="item in role_type" :label="item.label+''" :value="item.value+''"
                                    :key="item.value+''"></el-option>
                            </el-select>
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="权限字符" prop="role_key">
                            <el-input v-model="form.role_key" clearable placeholder="请输入权限字符" />
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="12">
                        <el-form-item label="是否启用" prop="status">
                            <el-select v-model="form.status" placeholder="角色状态">
                                <el-option v-for="item in use_status" :label="item.label+''" :value="item.value+''"
                                    :key="item.value+''"></el-option>
                            </el-select>
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="数据范围" prop="data_scope">
                            <el-select v-model="form.data_scope" placeholder="数据范围">
                                <el-option :disabled="currentUserType != '0' && item.value == '1'"
                                    v-for="item in sys_data_scope" :label="item.label+''" :value="item.value+''"
                                    :key="item.value+''">
                                </el-option>
                            </el-select>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="12">
                        <el-form-item label="系统数据" prop="is_sys">
                            <el-select v-model="form.is_sys" placeholder="系统数据">
                                <el-option :disabled="currentUserType != '0' && item.value == '1'" v-for="item in yes_no"
                                    :label="item.label+''" :value="item.value+''" :key="item.value+''"></el-option>
                            </el-select>
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="归属机构" prop="office_id">
                            <el-tree-select v-model="form.office_id" :data="officeTree"
                                :props="{ value: 'id', label: 'label', children: 'children' }" value-key="id"
                                placeholder="选择归属机构" check-strictly :filter-node-method="filterNode" clearable filterable />
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-row>
                    <el-col :span="24">
                        <el-form-item label="备注" prop="remark">
                            <el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>
            <template #footer>
                <div class="dialog-footer">
                    <el-button type="primary" @click="submitForm">确 定</el-button>
                    <el-button @click="open = false">取 消</el-button>
                </div>
            </template>
        </el-dialog>
        <!-- 权限设置对话框 -->
        <el-dialog :title="'权限设置'" v-model="meneAuthOpen" width="600px" @close="menuAuth = {roleId: '',menuIds: []}"
            append-to-body>
            <el-row :gutter="10" class="mb8">
                <el-col :span="1.5">
                    <el-button type="info" plain icon="Sort" @click="handleExpand">展开/折叠</el-button>
                </el-col>
                <el-col :span="1.5">
                    <el-button type="info" plain icon="Sort" @click="handleSelect">全选/全不选</el-button>
                </el-col>
                <el-col :span="1.5">
                    <el-input v-model="menuName" placeholder="请输入菜单名称" clearable prefix-icon="Search"
                        style="margin-bottom: 20px" />
                </el-col>
            </el-row>
            <el-row>
                <el-col :span="24">
                    <div class="down-tree">
                        <el-tree @check-change="handleCheck" @check="handleCheckChange" :show-checkbox="true"
                            :data="menuTreeList" :props="{ label: 'menuName', children: 'children' }"
                            :filter-node-method="filterNode" ref="menuTreeRef" node-key="menuId" highlight-current />
                    </div>
                </el-col>
            </el-row>
            <template #footer>
                <div class="dialog-footer">
                    <el-button type="primary" @click="submitMenuAuth">确 定</el-button>
                    <el-button @click="meneAuthOpen = false">取 消</el-button>
                </div>
            </template>
        </el-dialog>
    </div>
</template>

<script setup>
	import { getRoleList, changeStatus, getRoleInfo, updateRoleInfo, addRoleInfo, delRoleInfo, updateMenuAuth } from "@/api/system/role"
	import { menuList, menuListByRoleId } from "@/api/system/menu"
	import { getCurrentInstance, nextTick } from "vue";
	import useUserStore from '@/store/modules/user'
	import { getOfficeTree } from '@/api/system/office';
	import { useRouter } from "vue-router";

	/* this */
	const { proxy } = getCurrentInstance();
	/* 当前用户类型 */
	const currentUserType = useUserStore().userType;
	/* 路由 */
	const router = useRouter();

	/* 字典数据 (数据范围、是否启用、角色类型) */
	const { sys_data_scope, use_status, role_type, yes_no } = proxy.useDict("sys_data_scope", "use_status", "role_type", "yes_no");
	/* 加载动画 */
	const loading = ref(false);
	/* 角色列表 */
	const roleList = ref([]);
	/* 总数 */
	const total = ref(0);
	/* 创建日期 */
	const dateRange = ref([]);
	/* 是否禁用修改按钮 */
	const hasEdit = ref(true);
	/* 是否禁用删除按钮 */
	const hasDel = ref(true);
	/* 角色Dialog的标题 */
	const title = ref('');
	/* 角色Dialog的显隐 */
	const open = ref(false);
	/* 表格选中行的id */
	const ids = ref([]);
	/* 表格选中行是否为系统数据 */
	const isSys = ref([]);
	/* 表单所属机构数据 */
	const officeTree = ref([]);
	/* 权限设置dialog显隐 */
	const meneAuthOpen = ref(false);
	/* 菜单数据 */
	const menuTreeList = ref([]);
	/* 菜单树状图数据过滤词 */
	const menuName = ref('');
	/* 是否展开 */
	const expanded = ref(false);

	/* 查询参数 */
	const data = reactive({
		queryParams: {
			pageNum: 1,
			pageSize: 10,
			name: '',
			enname: '',
			status: ''
		},
		form: {},
		rules: {
			name: [{ required: true, message: '角色名称不能为空', trigger: 'change' }],
			enname: [{ required: true, message: '英文名称不能为空', trigger: 'change' }],
			role_key: [{ required: true, message: '权限字符不能为空', trigger: 'change' }],
			office_id: [{ required: true, message: '归属部门不能为空', trigger: 'change' }],
		},
		menuAuth: {
			roleId: '',
			menuIds: [],
		}
	})
	/* 转为ref */
	const { queryParams, form, rules, menuAuth } = toRefs(data);
	/* 重置表单参数 */
	function reset() {
		form.value = {
			name: '',
			enname: '',
			status: '0',
			data_scope: '2',
			role_type: 'assignment',
			role_key: '',
			is_sys: '0',
			office_id: undefined,
			remark: ''
		}
		proxy.resetForm("roleFormRef");
	}
	/* 重置查询参数 */
	function resetQueryParams() {
		queryParams.value = {
			pageNum: 1,
			pageSize: 10,
			name: '',
			enname: '',
			status: ''
		}
	}
	/* 加载机构数据 */
	async function loadOfficeTree() {
		await getOfficeTree().then(response => {
			officeTree.value = response.data;
		});
	}
	/* 监听过滤词 */
	watch(menuName, val => {
		proxy.$refs["menuTreeRef"].filter(val);
	});
	/* 通过条件过滤节点  */
	const filterNode = (value, data) => {
		if (!value) return true;
		if (data.label) {
			return data.label.indexOf(value) !== -1;
		} else {
			return data.menuName.indexOf(value) !== -1;
		}
	};
	/* 展开/折叠按钮 */
	function handleExpand() {
		expanded.value = !expanded.value;
		const menuTreeNodeList = proxy.$refs["menuTreeRef"].store._getAllNodes();
		for (let i = 0; i < menuTreeNodeList.length; i++) {
			menuTreeNodeList[i].expanded = expanded.value;
		}
	}
	/* 全选/全不选按钮 */
	function handleSelect() {
		const menuTree = (proxy.$refs["menuTreeRef"]);
		const menuTreeNodeList = menuTree.store._getAllNodes();
		if (menuAuth.value.menuIds.length == 0) {
			for (let i = 0; i < menuTreeNodeList.length; i++) {
				menuAuth.value.menuIds.push(menuTreeNodeList[i].data.menuId);
			}
		} else {
			menuAuth.value.menuIds = [];
		}
		menuTree.setCheckedKeys(menuAuth.value.menuIds);
	}
	/* 处理树状图复选框选中时 */
	function handleCheck(data, hasChecked, hasChildrenChecked) {
		/* if (hasChecked && data.parentId) {
			proxy.$refs["menuTreeRef"].setChecked(data.parentId, true, false);
		} */
	}
	/* 处理树状图复选框选中 */
	function handleCheckChange(currentNode, checkedNode) {
		menuAuth.value.menuIds = checkedNode.checkedNodes.map(item => item.menuId);
		checkedNode.halfCheckedKeys.forEach(item => { menuAuth.value.menuIds.push(item) });
		console.log('menuAuth.value.menuIds', menuAuth.value.menuIds)
	}
	/* 搜索按钮 */
	function handleQuery() {
		queryParams.value.pageNum = 1;
		bindRoleList();
	}
	/* 重置按钮 */
	function resetQuery() {
		resetQueryParams();
		handleQuery();
	}
	/* 处理表格选中 */
	function handleSelectionChange(selection) {
		ids.value = selection.map(item => parseInt(item.id));
		isSys.value = selection.map(item => item.is_sys);
		hasEdit.value = selection.length != 1;
		hasDel.value = !selection.length;
	}
	/* 修改角色状态 */
	function handleStatusChange(row) {
		let text = row.status === "0" ? "启用" : "停用";
		proxy.$modal.confirm("确认要" + text + "“" + row.name + "”角色" + "吗?").then(() => {
			return changeStatus(row.id, row.status);
		}).then(response => {
			proxy.$modal.msgSuccess(text + "成功");
		}).catch(() => {
			row.status = row.status === "0" ? "1" : "0";
		})
	}
	/* 表单提交 */
	async function submitForm() {
		proxy.$refs["roleFormRef"].validate(valid => {
			if (valid) {
				if (form.value.id) {
					updateRoleInfo(form.value).then(response => {
						if (response.code == 200) {
							proxy.$modal.msgSuccess("修改成功");
							bindRoleList();
						} else {
							proxy.$modal.msgError("修改失败");
						}
					})
				} else {
					addRoleInfo(form.value).then(response => {
						if (response.code == 200) {
							proxy.$modal.msgSuccess("新增成功");
							bindRoleList();
						} else {
							proxy.$modal.msgError("新增失败");
						}
					})
				}
			}
		})
	}
	/* 处理权限设置按钮 */
	async function handleMenuAuth(row) {
		menuAuth.value.roleId = row.id;
		// 获取菜单数据
		await menuList().then(response => {
			menuTreeList.value = proxy.handleTree(response.data, "menuId", "parentId");
		})
		// 获取角色权限信息
		const response = await menuListByRoleId(row.id);

		menuAuth.value.menuIds = response.data;

		meneAuthOpen.value = true;
		nextTick(() => {
			proxy.$refs["menuTreeRef"].setCheckedKeys(menuAuth.value.menuIds);
		})
	}
	/** 处理分配用户按钮 */
	function handleAuthUser(row) {
		router.push("/institutionuser/role-auth/user/" + row.id);
	}
	/* 提交权限设置 */
	function submitMenuAuth() {
		proxy.$modal.confirm("确认要设置该权限？").then(() => {
			return updateMenuAuth(menuAuth.value);
		}).then(response => {
			if (response.code == 200) {
				proxy.$modal.msgSuccess("设置成功");
				bindRoleList();
			} else {
				proxy.$modal.msgError("设置失败");
			}
		})
	}
	/* 处理添加操作 */
	function handleAdd() {
		reset();
		loadOfficeTree();
		title.value = "新增角色";
		open.value = true;
	}
	/* 处理修改操作 */
	async function handleUpdate(row) {
		if (currentUserType != '0' && isSys.value.some(item => item == "1")) {
			proxy.$modal.msgError("不能修改系统数据");
			return;
		}

		const roleIds = row.id || ids.value;
		reset();
		await loadOfficeTree();
		const response = await getRoleInfo(roleIds);
		form.value = response.data;
		form.value.office_id = parseInt(form.value.office_id);
		title.value = "修改角色";
		open.value = true;
	}
	/* 处理删除操作 */
	function handleDelete(row) {
		if (currentUserType != '0' && isSys.value.some(item => item == "1")) {
			proxy.$modal.msgError("不能删除系统数据");
			return;
		}
		const roleIds = row.id || ids.value;
		proxy.$modal.confirm("确认要删除编号为“" + roleIds + "”的角色吗？").then(() => {
			return delRoleInfo(roleIds);
		}).then(response => {
			if (response.code == 200) {
				proxy.$modal.msgSuccess("删除成功");
				bindRoleList();
			} else {
				proxy.$modal.msgError("删除失败");
			}
		})

	}

	/* 绑定角色列表 */
	async function bindRoleList() {
		loading.value = true;
		await getRoleList(proxy.addDateRange(queryParams.value, dateRange.value)).then(response => {
			roleList.value = response.data;
			total.value = response.total;
			loading.value = false;
		})
	}

	bindRoleList();
</script>

<style>
.office-label {
    height: 40px;
    background: #f8fcff;
    line-height: 40px;
    padding-left: 10px;
    font-weight: bold;
    border: 0.5px solid #e2e2e2;
    border-radius: 5px;
}

.app-container {
    padding-top: 0px;
}

.down-tree {
    height: 500px;
    display: block;
    overflow-y: scroll;
    border: 0.5px solid #e7e7e7;
    border-radius: 1%;
}
</style>
